'''
This module is used to get information from baiyunhuanghe.
It fetches information from proper pages, parse it and return pythonic results.
'''
import urllib2
import re

from BeautifulSoup import BeautifulSoup

from byhh.settings import ITEM_MAP_DICT
from byhh.utils.urlmaker import make_article_list_url

FILE_RE = re.compile('&file=[^&]*&')

def get_item_field_content(td):
    '''
    Get the content of each field of an article item.
    An article item can be something like
            <td><a href="xxx">content</a></td>
    or directly: 
            <td>content</td>
    '''
    a = td.find("a")
    return a.string if a else td.string

def get_article_item_info(tr, map_dict):
    '''
    A tr is an unit which contains info about an article item. 
    A map_dict is a mapping between the info and the index of each td.
    This function translate a tr to an info dict according to the map_dict.
    '''
    article_item_info = {}
    tds = tr.findAll("td")
    keys = map_dict.keys()
    for key in keys: 
        related_td = tds[ map_dict[key] ]
        article_item_info[key] = get_item_field_content(related_td)
        if key == "title":
            title_a = related_td.find("a")
            title_href = title_a["href"]
            file_snippets = FILE_RE.findall(title_href)
            if len(file_snippets) >= 1:
                article_item_info["file"] = file_snippets[0][6: -1]
            else:
                article_item_info["file"] = None
    return article_item_info 

def get_article_list_info(board, start=None):
    '''
    Get the info of article list.
    Parameters:
      - board(required): The board name. Available value is in byhh.settings.BOARD_LIST.
      - start(optional): The start article id in the page. Begin at 1.
                         If not provided, the latest page is used.
                         If start is smaller than 1, 1 will be used.
                         If start is bigger than (<the biggest number> - 19),
                         (<the biggest number> - 19) will be used.
                         The above two guide is done by byhh.
    Return:
      [
          {
              "num": "12",
              "user_name": "shifan",
              "datetime": "11th Nov",
              "title": "hey, body.",
              "click": "5",
              "file": "M.1231244.A",
          },
          {
              "num": "12",
              "user_name": "shifan",
              "datetime": "11th Nov",
              "title": "hey, body.",
              "click": "5",
              "file": "M.1231244.A",
          },
          {
              "num": "12",
              "user_name": "shifan",
              "datetime": "11th Nov",
              "title": "hey, body.",
              "click": "5",
              "file": "M.1231244.A",
          },
      ]
    Note:
      For byhh article items inside a board, there are two identifications for an article.
      <num> and <start>. <num> begin at 0, but <start> begin at 1.
    '''
    url = make_article_list_url(board, start)
    if not url:
        return None

    resp = urllib2.urlopen(url)
    data = resp.read()

    soup = BeautifulSoup(data)
    article_list = []

    # Iterate through the article list table to get Article List Info
    article_list_table = soup.find("table", {"style": "border-collapse: collapse;text-align:left;"})
    article_list_trs = article_list_table.findAll("tr") 
    for article_tr in article_list_trs:
        # If the tr contains element <font> recursively, the tr is  in top-articles.
        font = article_tr.find("font")
        if font:
            continue
        article_info = get_article_item_info(article_tr, ITEM_MAP_DICT)
        article_list.append(article_info)
    return article_list
